//***************************************************************************//
//*
//* 内容摘要：SDK对外主动接口类
//*	
//* 当前版本：V1.0		
//* 作    者：zhfayuan
//* 完成日期：2017-11-22
//**************************************************************************//
#if !defined(SDTERMINAL_H)
#define SDTERMINAL_H

#include "SDCommon.h"
#include "SDThread.h"
#include "SDLog.h"
#include "SDMutex.h"
#include "SDClientCommon.h"
#include "SDTermCommon.h"
#include "SDTermIFace.h"
#include "CmdProtocolStruct.h"


class CSDTerminal;
//SDK接口类
class  CSDTerminal : public CSDMessage, public CSDSingleComSocket
{
    public:

        DLLEXPORT CSDTerminal(CSDTermCmdIFace* pCltIFace, std::string strPackageName,UINT LoginCode,BYTE byTermType = TERM_TYPE_PC_W, BOOL bUseInternalTimestamp = TRUE);
        DLLEXPORT virtual ~CSDTerminal();

        BOOL m_bUseInternalTimestamp;
    public: 
        // 登录服务器
        DLLEXPORT int IFace_Online(const char* strIp,const int nPort,BYTE byUserType, UINT unDomainId = 1, BYTE byNetType = OPERATOR_OTHER);

        // 从服务器下线
        DLLEXPORT void IFace_Offline();
        // 发送依思自定义命令
        DLLEXPORT void IFace_SendBroadcast(UINT subCmd,BYTE* buf, UINT unLen);
        DLLEXPORT int IFace_SendCmd(UINT cmd,UINT subCmd,BYTE protocol,BYTE* buf, UINT unLen);

        //获得当前的版本号
        DLLEXPORT UINT IFace_GetVersion();

        DLLEXPORT std::string IFace_GetServerIp();
    private:

        //底层TCP链接的一些错误处理
        void Error(int nErrorId);

        void Command(PACK_MESSAGE* pack);
        int  ProcessMessage(void* pParam);
        BOOL RespondPackMessage(PACK_MESSAGE *pack)
        {
            CSDSingleComSocket::UpdateSynRetBuf(pack);
            return TRUE;
        }

    private:
        BOOL mfIsWork() { return CSDSingleComSocket::IsWork() && m_bOnlineStatus; };
        BOOL mfInit();
        void mfClose(BOOL bCloseHandThread, BOOL bCloseMessageThread = TRUE, BOOL bCloseTcpThread = TRUE,BOOL bCloseAuthThread = TRUE);

        BOOL mfConnect(char* strIp, int nPortId, int nPingPort);
        int  mfProcessBroadcase(PACK_MESSAGE* pack);
        BOOL mfSendCmd1(USHORT shCmdMessage);
        BOOL mfSendCmd2(USHORT shCmdMessage, UINT64 unSrcUid, UINT64 unDesUid,UINT64 unOther1 = 0, UINT64 unOther2 = 0);
        void mfSendCmd3(USHORT shCmdMessage, UINT64 unSrcUid, UINT64 unOther1 = 0, UINT64 unOther2 = 0, UINT unDataLen = 0, BYTE* byData = NULL);

        int  mfOnLine(BYTE byUserType,BYTE byNetType);
        void mfOffLine();

        int  mfConnectMsgServer(BYTE byUserType, BYTE byNetType);

        void mfHandleMessage(PACK_MESSAGE *pack);
        static int IsTerminalCloseRequest(void* pParam);

    private:
        void PrintHex(BYTE *pre, BYTE*by, UINT unLen);
		void MyAuthIdle(UINT &uSendInterval, UINT &unState);
        void MyPubKeyExchangeSerRandom(UINT &uSendInterval,UINT &unState,SM_RANDOM &stRandom);
        void MyRandomExchangeSerPubKey(UINT &uSendInterval,UINT &unState,SM_RANDOM &stRandom);
        void MyEmptyExchangeSerRandom(UINT &uSendInterval,UINT &unState,SM_RANDOM &stRandom);
        void MyCompositeRandomExchangeVkek(UINT &uSendInterval,UINT &unState,SM_RANDOM &stRandom);
    private:	
        //TCP心跳线程
        static int HandleThread(void* pParam);
        static int HandleThreadClose(void* pParam);
        //自动重连线程
        static int AutoReconnectThread(void* pParam);
        static int AutoReconnectThreadClose(void* pParam);
        //加密认证线程
        static int AuthThread(void* pParam);
        static int AuthThreadClose(void* pParam);

        static int SDEnum(struct stIdentity& identity);

    private:
        CSDThread           m_AuthThread;
        CSDEvent            m_AuthRetryEvent;
        CSDEvent            m_AutoReconnectEvent;
    private:

        CSDTermCmdIFace*	m_pCltIFace;
        BOOL				m_bNoblockRequest;

        SM2_KEY_PAIR        m_stKeyPair;
        BYTE                m_byVek[VEK_LEN];

        BYTE                m_unSeq;

        CSDThread           m_AutoReconnectThread;
        BOOL                m_bAutoReconnectThreadCreate;
        char				m_strDomainSerIp[128];
        UINT                m_unSerPort;

        BYTE				m_unUserType;
        BYTE				m_byTermType;
        BYTE				m_byNetType;

        //0表示离线，1表示在线
        BOOL				m_bOnlineStatus;
        //资源是否回收
        BOOL				m_bCloseFlag;
        //是否处于上位状态
        //BOOL				m_bOnPosition;
        //是否已经通知外层底层连接错误，该标志用于避免多次通知的情况
        BOOL				m_bNotifyError;	
        //底层连接错误原因
        UINT				m_unErrorReason;	

        void*				m_execs;
        void*				m_cmdRecvCs;
        void*               m_avCs;


        //要发出的通用请求包,构造时分配内存
        PACK_MESSAGE*		m_packRequest;		

        //用于给当前服务器发送周期性心跳包的线程
        CSDThread			m_HandleThread;
        CSDEvent			m_HandleEvent;


        bool				m_bTcpRecvThreadIsCreate;


        //收到当前服务器心跳包的计数，用于判断该客户端是否已经处于无效状态
        UINT				m_unCurrHandPacketCount;

        //标识本次主动登录（不包括内部掉线重连，内部重连使用不变的唯一登录码）的唯一登录码
        UINT				m_unLogonCode;	
};
#endif // !defined(SDTERMINAL_H)
